package com.fzhucc.modules.sciPersonnelInfo.service.impl;

import com.fzhucc.exception.BadRequestException;
import com.fzhucc.modules.sciPersonnelInfo.domain.SciExpertConsultationConfig;
import com.fzhucc.modules.sciPersonnelInfo.domain.SciExpertOfflineConfig;
import com.fzhucc.modules.sciPersonnelInfo.domain.SciExpertReservation;
import com.fzhucc.modules.sciPersonnelInfo.domain.SciPersonnelInfo;
import com.fzhucc.modules.sciPersonnelInfo.domain.dto.*;
import com.fzhucc.modules.sciPersonnelInfo.repository.SciExpertConsultationConfigRepository;
import com.fzhucc.modules.sciPersonnelInfo.repository.SciExpertOfflineConfigRepository;
import com.fzhucc.modules.sciPersonnelInfo.repository.SciExpertReservationRepository;
import com.fzhucc.modules.sciPersonnelInfo.repository.SciPersonnelInfoRepository;
import com.fzhucc.modules.sciPersonnelInfo.service.SciExpertReservationService;
import com.fzhucc.modules.sciPersonnelInfo.service.mapstruct.SciExpertConsultationConfigMapper;
import com.fzhucc.modules.sciPersonnelInfo.service.mapstruct.SciExpertOfflineConfigMapper;
import com.fzhucc.modules.sciPersonnelInfo.service.mapstruct.SciExpertReservationMapper;
import com.fzhucc.modules.sciPersonnelInfo.service.mapstruct.SciPersonnelInfoMapper;
import com.fzhucc.modules.system.service.UserService;
import com.fzhucc.modules.system.service.dto.UserDto;
import com.fzhucc.utils.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @author yyg
 * @description 服务实现
 * @date 2023-10-20
 **/
@Service
@RequiredArgsConstructor
public class SciExpertReservationServiceImpl implements SciExpertReservationService {

    private final SciExpertReservationRepository expertReservationRepository;
    private final SciExpertReservationMapper expertReservationMapper;

    private final SciPersonnelInfoRepository expertRepository;

    private final SciExpertConsultationConfigRepository expertConsultationConfigRepository;

    private final SciExpertOfflineConfigRepository expertOfflineConfigRepository;

    private final SciPersonnelInfoMapper expertMapper;

    private final SciExpertConsultationConfigMapper expertConsultationConfigMapper;

    private final SciExpertOfflineConfigMapper expertOfflineConfigMapper;

    private final UserService userService;

    @Override
    public Map<String, Object> queryAll(SciExpertReservationQueryCriteria criteria, Pageable pageable) {
        Page<SciExpertReservation> page = expertReservationRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        Page<SciExpertReservationDto> map = page.map(expertReservationMapper::toDto);
        List<SciExpertReservationDto> list = map.getContent();
        if (list != null && list.size() > 0) {
            for (SciExpertReservationDto dto : list) {
                Integer expertId = dto.getExpertId();
                Optional<SciPersonnelInfo> res = expertRepository.findById(expertId);
                if (res.isPresent()) {
                    SciPersonnelInfoDto sciPersonnelInfoDto = expertMapper.toDto(res.get());
                    dto.setExpertDto(sciPersonnelInfoDto);
                }

                Integer expertConsultationId = dto.getExpertConsultationId();
                if (expertConsultationId != null && expertConsultationId != 0) {
                    Optional<SciExpertConsultationConfig> res2 = expertConsultationConfigRepository.findById(expertConsultationId);
                    if (res2.isPresent()) {
                        SciExpertConsultationConfigDto expertConsultationConfigDto = expertConsultationConfigMapper.toDto(res2.get());
                        dto.setExpertConsultationConfigDto(expertConsultationConfigDto);
                    }
                }

                Integer expertOfflineId = dto.getExpertOfflineId();
                if (expertOfflineId != null && expertOfflineId != 0) {
                    Optional<SciExpertOfflineConfig> res3 = expertOfflineConfigRepository.findById(expertOfflineId);
                    if (res3.isPresent()) {
                        SciExpertOfflineConfigDto expertOfflineConfigDto = expertOfflineConfigMapper.toDto(res3.get());
                        dto.setExpertOfflineConfigDto(expertOfflineConfigDto);
                    }
                }
            }
        }
        return PageUtil.toPage(map);
    }

    @Override
    public List<SciExpertReservationDto> queryAll(SciExpertReservationQueryCriteria criteria) {
        return expertReservationMapper.toDto(expertReservationRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public SciExpertReservationDto findById(Integer id) {
        SciExpertReservation expertReservation = expertReservationRepository.findById(id).orElseGet(SciExpertReservation::new);
        ValidationUtil.isNull(expertReservation.getId(), "SciExpertReservation", "id", id);
        return expertReservationMapper.toDto(expertReservation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SciExpertReservationDto create(SciExpertReservation resources) {
        return expertReservationMapper.toDto(expertReservationRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SciExpertReservationDto createByH5(SciExpertReservationOrderDto dto) {
        SciExpertReservation res = new SciExpertReservation();
        Long userId = null;
        try {
            userId = SecurityUtils.getCurrentUserId();
        } catch (Exception e) {

        }

        Integer expertId = dto.getExpertId();
        Optional<SciPersonnelInfo> ops = expertRepository.findById(expertId);
        if (!ops.isPresent()) {
            throw new BadRequestException("劳模工匠未找到");
        }
        res.setExpertId(expertId);
        res.setDay(dto.getDay());
        res.setName(dto.getName());
        res.setPhone(dto.getPhone());
        Integer expertOfflineId = dto.getExpertOfflineId();
        Integer expertConsultationId = dto.getExpertConsultationId();
        res.setExpertOfflineId(expertOfflineId);
        res.setExpertConsultationId(expertConsultationId);
        res.setUnit(dto.getUnit());
        res.setUserId(userId);
        if (expertConsultationId != null && expertConsultationId != 0) {
            Optional<SciExpertConsultationConfig> ops1 = expertConsultationConfigRepository.findById(expertConsultationId);
            if (!ops1.isPresent()) {
                throw new BadRequestException("专家线上咨询配置id未找到");
            }
            res.setType("线上咨询");
        } else if (expertOfflineId != null && expertOfflineId != 0) {
            Optional<SciExpertOfflineConfig> ops2 = expertOfflineConfigRepository.findById(expertOfflineId);
            if (!ops2.isPresent()) {
                throw new BadRequestException("专家线下辅导配置id未找到");
            }
            res.setType("线下辅导");

            //判断此专家的限制人数是否>=预约人数  否则不让预约
            SciExpertOfflineConfig sciExpertOfflineConfig = ops2.get();
            Integer limitsCount = sciExpertOfflineConfig.getLimitsCount();
            List<SciExpertReservation> list = expertReservationRepository.findByExpertOfflineId(sciExpertOfflineConfig.getId());
            if (list != null && limitsCount!=null) {
                if (list.size() <= limitsCount) {

                } else {
                    throw new BadRequestException("该劳模已预约满，无法预约");
                }
            }
        } else {
            res.setType("无");
        }

        //不用扣积分
        /*UserDto userDto = userService.findById(userId);
        if (userDto.getIntegral() == null) {
            throw new BadRequestException("未找到用户积分");
        }
        Integer integral = userDto.getIntegral();//用户拥有的积分
        if (integral < 50) {
            throw new BadRequestException("积分不足");
        }
        int result_integral = integral - 50;
        userDto.setIntegral(result_integral);
        userService.updateIntegral(userId, result_integral);*/
        return expertReservationMapper.toDto(expertReservationRepository.save(res));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SciExpertReservation resources) {
        SciExpertReservation expertReservation = expertReservationRepository.findById(resources.getId()).orElseGet(SciExpertReservation::new);
        ValidationUtil.isNull(expertReservation.getId(), "ExpertReservation", "id", resources.getId());
        expertReservation.copy(resources);
        expertReservationRepository.save(expertReservation);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            expertReservationRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<SciExpertReservationDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (SciExpertReservationDto expertReservation : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("预约人", expertReservation.getName());
            map.put("单位/学校", expertReservation.getUnit());
            map.put("手机号", expertReservation.getPhone());
            map.put("被预约专家id", expertReservation.getExpertId());
            map.put("日期", expertReservation.getDay());
            map.put("关联线上预约配置id  不为空说明关联了 线上预约", expertReservation.getExpertConsultationId());
            map.put("关联线下辅导配置id  不为空说明关联了 线下辅导", expertReservation.getExpertOfflineId());
            map.put("字典 专家预约类型 字典 expert_reservation_type", expertReservation.getType());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}
